package org.yelongframework.model.support.service.adapter;

import java.util.List;

import org.yelongframework.core.interceptor.Intercepts;
import org.yelongframework.core.interceptor.Invocation;
import org.yelongframework.core.interceptor.Signature;
import org.yelongframework.lang.Nullable;
import org.yelongframework.model.Modelable;
import org.yelongframework.model.collector.ModelCollectors;
import org.yelongframework.model.service.SqlModelService;
import org.yelongframework.model.service.interceptor.ModelServiceInterceptor;

/**
 * SQL模型服务适配器拦截器，拦截所有方法调用
 * 
 * @since 1.0.0
 */
@Intercepts({
		@Signature(type = SqlModelServiceAdapter.class, method = "removeById", args = { Class.class, Object.class }),
		@Signature(type = SqlModelServiceAdapter.class, method = "removeByIds", args = { Class.class, Object[].class }),
		@Signature(type = SqlModelServiceAdapter.class, method = "modifyById", args = Modelable.class),
		@Signature(type = SqlModelServiceAdapter.class, method = "modifySelectiveById", args = Modelable.class),
		@Signature(type = SqlModelServiceAdapter.class, method = "countById", args = { Class.class, Object.class }),
		@Signature(type = SqlModelServiceAdapter.class, method = "existById", args = { Class.class, Object.class }),
		@Signature(type = SqlModelServiceAdapter.class, method = "findAll", args = { Class.class, Object.class }),
		@Signature(type = SqlModelServiceAdapter.class, method = "findById", args = { Class.class, Object.class }) })
public abstract class SqlModelServiceAdapterInterceptor implements ModelServiceInterceptor {

	@SuppressWarnings("unchecked")
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		String methodName = invocation.getMethodName();
		Object[] args = invocation.getArgs();
		if ("removeById".equals(methodName)) {
			return removeById(invocation, (Class<? extends Modelable>) args[0], args[1]);
		} else if ("removeByIds".equals(methodName)) {
			return removeByIds(invocation, (Class<? extends Modelable>) args[0], (Object[]) args[1]);
		} else if ("modifyById".equals(methodName)) {
			return modifyById(invocation, (Modelable) args[0]);
		} else if ("modifySelectiveById".equals(methodName)) {
			return modifySelectiveById(invocation, (Modelable) args[0]);
		} else if ("countById".equals(methodName)) {
			return countById(invocation, (Class<? extends Modelable>) args[0], args[1]);
		} else if ("existById".equals(methodName)) {
			return existById(invocation, (Class<? extends Modelable>) args[0], args[1]);
		} else if ("findAll".equals(methodName)) {
			return findAll(invocation, (Class<? extends Modelable>) args[0]);
		} else if ("findById".equals(methodName)) {
			return findById(invocation, (Class<? extends Modelable>) args[0], args[1]);
		}
		throw new UnsupportedOperationException("未知的适配器方法：" + invocation.getMethod());
	}

	protected boolean removeById(Invocation invocation, Class<? extends Modelable> modelClass, Object id) {
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.removeByOnlyPrimaryKeyEQ(modelClass, id)) > 0;
	}

	protected Integer removeByIds(Invocation invocation, Class<? extends Modelable> modelClass, Object[] ids) {
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.removeByOnlyPrimaryKeyContains(modelClass, ids));
	}

	protected boolean modifyById(Invocation invocation, Modelable model) {
		ModelCollectors.setModifySelective(false);
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.modifyModelByOnlyPrimaryKeyEQ(model, null)) > 0;
	}

	protected boolean modifySelectiveById(Invocation invocation, Modelable model) {
		ModelCollectors.setModifySelective(true);
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.modifyModelByOnlyPrimaryKeyEQ(model, null)) > 0;
	}

	protected Long countById(Invocation invocation, Class<? extends Modelable> modelClass, Object id) {
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.countByOnlyPrimaryKeyEQ(modelClass, id));
	}

	protected boolean existById(Invocation invocation, Class<? extends Modelable> modelClass, Object id) {
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.existByOnlyPrimaryKeyEQ(modelClass, id));
	}

	@Nullable
	protected <M extends Modelable> List<M> findAll(Invocation invocation, Class<M> modelClass) {
		return getInterceptorWrapAfterSqlModelService(invocation).collect(ModelCollectors.findAll(modelClass));
	}

	@Nullable
	protected <M extends Modelable> M findById(Invocation invocation, Class<M> modelClass, Object id) {
		return getInterceptorWrapAfterSqlModelService(invocation)
				.collect(ModelCollectors.getModelByOnlyPrimaryKeyEQ(modelClass, id));
	}

	/**
	 * @param invocation 调用信息
	 * @return 获取拦截器包装之后的{@link SqlModelService}
	 */
	protected abstract SqlModelService getInterceptorWrapAfterSqlModelService(Invocation invocation);

}
